class Solution(object):
    def myAtoiSimple(s):
        """
        :type s: str
        :rtype: int
        一般方法
        """
        MAX = 2**31 // 10
        curIndex, flag, edge, OF = 0, 1, 7, 0
        res = 0
        while curIndex<len(s) and s[curIndex]==' ':
            curIndex += 1
        if curIndex < len(s) and (s[curIndex] == '-' or s[curIndex] == '+'):
            flag, edge = [[1, 7], [0, 8]][['+', '-'].index(s[curIndex])]
            curIndex += 1
        while curIndex < len(s) and s[curIndex]>='0' and s[curIndex]<='9':
            """
            based on (MAX = 2**31-1)
            temp = int(s[curIndex])
            if res > (MAX-temp) // 10:
                OF, curIndex = 1, len(s)
            res = res*10 + temp
            curIndex += 1
            """
            temp = int(s[curIndex])
            if res > MAX:
                OF, curIndex = 1, len(s)
            if res == MAX:
                if temp > edge:
                    OF, curIndex = 1, len(s)
            res = res*10 + temp
            curIndex += 1
        if flag:
            return [res, 2**31-1][OF]  
        return [-res, -2**31][OF]

"""
以下是官方给出的自动机法（有限状态机法）
逻辑更清晰，规则更容易扩展
"""
INT_MAX = 2 ** 31 - 1
INT_MIN = -2 ** 31
class Automaton:
    def __init__(self):
        self.state = 'start'
        self.sign = 1
        self.ans = 0
        """
            状态表table在下面展示,下一刻状态由当前状态和输入符号决定
            输入:
                ''      自动机的初始ans为0 无动作遍历结束直接返回0
                ' '     初始状态 start 第一个输入为一个space 在表中查找发现状态依旧为start ans无变化 遍历结束返回0
                ' 12'   初始状态 start 第一个输入为一个space 状态改为start ans无变化
                                     第二个输入为1 状态改为 number  ans = ans*10 + 1 判断是否溢出 
                                     第三个输入为2 状态保持不变  ans = ans*10 + 1 判断是否溢出
                                     遍历结束 返回 ans值
                ' -12'  与示例3相近 在第二个输入时 状态改为signed 将自动机的sign改为-1
                ' -+12' 在示例4的第三个输入时 当前状态为signed 输入为+ 查表发现状态应改为end 于是将状态改为end
                        在此后的输入中状态一直保持end直至遍历结束 ans为0

        """
        self.table = {      # ' '       +/-         number        other
            'start':        ['start', 'signed'  , 'in_number'   , 'end'],
            'signed':       ['end'  , 'end'     , 'in_number'   , 'end'],
            'in_number':    ['end'  , 'end'     , 'in_number'   , 'end'],
            'end':          ['end'  , 'end'     , 'end'         , 'end'],
        }
        
    def get_col(self, c):
        if c.isspace():
            return 0
        if c == '+' or c == '-':
            return 1
        if c.isdigit():
            return 2
        return 3

    def get(self, c):
        self.state = self.table[self.state][self.get_col(c)]
        if self.state == 'in_number':
            self.ans = self.ans * 10 + int(c)
            self.ans = min(self.ans, INT_MAX) if self.sign == 1 else min(self.ans, -INT_MIN)
        elif self.state == 'signed':
            self.sign = 1 if c == '+' else -1

class OffcialSolution:
    def myAtoi(str: str) -> int:
        automaton = Automaton()
        for c in str:
            automaton.get(c)
        return automaton.sign * automaton.ans
